Projekt Pronal Projekt Pronal

Kazalo:
Sofinasiranje projekta
Starejši - učbenik...
Tekmovanja...
Tekmovanja - dopolni...
Tekmovanja - Parsons...
Tekmovanja - popravi...
Starejši - zbirka nalog
Funkcije
If stavek
Izpisi
Množice
Nizi
Pisanje in popravljanje programa
Seznami in nizi
Slovarji
Spoznajmo Python
Uvod v funkcije
Zanka for
Zanka while
Zanka while

Zanka while


Naloga 2 (stran 52)

Naloga zasnovana na nalogi https://lusy.fri.uni-lj.si/ucbenik/book/1203/index9.html

1. podnaloga

Napišite program, ki te vpraša po nizu z 'Vnesi niz:' in prebere nek niz in ga 10-krat izpiše.

Primer:

Vnesi niz: tomo
tomo
tomo
tomo ...

Uradna rešitev

#
niz = input("Vnesi niz: ")
i = 1
while i <= 10:
  print(niz)
  i += 1

2. podnaloga

Dopolni ta program tako, da te najprej vpraša po celem številu n z 'Vpiši poljuno celo število: ' ter prebere to število. Nato te vpraša po nekem nizu z 'Vpiši niz: ' ter prebere ta niz. Program naj na koncu n-krat izpiše prebrani niz.

Primer:

>>> Vpiši poljubno celo število: 3
>>> Vpiši niz: banana
banana
banana
banana

Uradna rešitev

#
n = int(input("Vpiši poljubno celo število: "))
niz = input("Vpiši niz: ")
i = 1
while i <= n:
  print(niz)
  i += 1

Naloga 5 (stran 52)

https://lusy.fri.uni-lj.si/ucbenik/book/1203/index9.html

1. podnaloga

Naslednji program naj bi prebral števili a in b (pri čemer predpostavi, da je a manjše od b) in izpisal vsoto števil od vključno a do vključno b, vendar ne deluje pravilno. Ugotovite, kaj je narobe, in ga popravi. (Izziv: to lahko narediš na vsaj tri različne načine. Znate najti vsaj dva?)

      a = int(input("Vnesi a: "))
      b = int(input("Vnesi b: "))
      vsota = a
      while a < b:
          vsota = vsota + a
          a = a + 1
      print(vsota)

Uradna rešitev

a = int(input("Vnesi a: "))
b = int(input("Vnesi b: "))
vsota = 0
while a <= b:
  vsota = vsota + a
  a = a + 1
print(vsota)

Podražitve

1. podnaloga

Nek izdelek naj bi se vsak teden podražil za 2%. Da bi razumeli, kaj to pomeni, napišite funkcijo koliko_tednov(cena), ki za dano začetno ceno (v €) tega izdelka vrne število tednov, ko bo cena dosegla ali presegla 1000€. Pri računanju ne zaokrožujte (cena je načeloma lahko tudi 1.234235€). V dobrih 6 letih (349 tednih natančno) bi se to zgodilo s kavo, ki sedaj stane 1€!

Za šaljivce, ki bodo funkcijo poklicali z negativno ceno ali ceno 0, vrnite -1.

Uradna rešitev

def koliko_tednov(cena):
    """Koliko tednov traja, da ceno ob
       2% podražitvi preseže 1000€"""
    if cena <= 0:  # odpravimo šaljivce
        return -1
    # smiselni podatki, računamo ...
    koncna_cena = 1000
    trenutna_cena = cena
    tednov = 0
    while trenutna_cena < koncna_cena:
        trenutna_cena = trenutna_cena * 1.02
        tednov += 1 # to je isto kot tednov = tednov + 1
    return tednov

Bakterije

1. podnaloga

Bakteriolog Bine preučuje bakterije. Naredil je sledeči poizkus: bakterije je zaprl v škatlico pravokotne oblike s pregrado na sredini, ki razdeli škatlico na dva kvadratna dela - poimenujmo ju regija A in regija B. Zunanje stene te škatlice so polprepustne, kar pomeni, da bacili lahko uidejo ven, vendar se ne morejo vrniti v škatlico, pregrada pa je prepustna, tj. bacili lahko prehajajo v obe smeri. Bine predvideva, da v neki časovni enoti $12 %$ vseh bacilov ostane v svoji regiji, po $22 %$ pa jih zapusti svojo regijo v vsaki od štirih smeri. Binetu sestavite program, ki bo prebral začetni masi bacilov (bacili so premajhni, da bi jih šteli posamično, zato jih "štejemo" kar v gramih) v vsaki od regij in izpisal število korakov, dokler skupna masa bacilov v obeh regijah ne pade pod $0.001$ grama. Tako bo lahko Bine primerjal teoretični izračun z izmerjenimi podatki in preveril svojo hipotezo. Predpostavite, da so podatki pravilni (nenegativni!).

Pozor! Premislite, kaj se dogaja na pregradi!

Za začetni masi $22.4$ in $13.5$ se število bakterij giblje

1, 5.658, 6.548
2, 2.11952, 2.03052
3, 0.7010568, 0.7099568
4, 0.240317312, 0.239427312
5, 0.08151208608, 0.08160108608
6, 0.0277336892672, 0.0277247892672
7, 0.00942749635085, 0.00942838635085
8, 0.00320554455929, 0.00320545555929
9, 0.00108986557016, 0.00108987447016
10 0.0003035929996319583 0.0003035829997319583

zato bi program izpisal $10$. Primer:

 Masa v regiji A: 22.4
 Masa v regiji B: 13.5
 Korakov: 10

Uradna rešitev

# Določimo število tednov, ko se ustrezno zmanjša začetna porazdelitev bakterij
masa_A = float(input('Masa v regiji A: '))
masa_B = float(input('Masa v regiji B: '))
korak = 0
while masa_A + masa_B >= 0.001: # skupna teža je še prevelika
    stara_A = masa_A # potrebovali bomo za izračun B-ja
    masa_A = masa_A * 0.12  # toliko jih ostane
    masa_A = masa_A + masa_B * 0.22 # toliko jih pa še pride iz B
    masa_B = masa_B * 0.12
    masa_B = masa_B + stara_A * 0.22
    korak += 1 # en korak več
print('Korakov:', korak)

Čaramo s celimi števili

1. podnaloga

Sestavite funkcijo obrni_stevilo(n), ki obrne pozitivno celo število. Iz $234$ torej naredi število $432$. Če je podatek slučajno negativen, vrni $0$!

Tisti, ki že poznate funcije in metode za delo z nizi, teh prijemov tukaj ne smete uporabiti. V tej nalogi torej nikjer ne smemo uporabljati nizov!

Uradna rešitev

def obrni_stevilo(n):
    """Funkcija obrne pozitivno celo število"""
    if n < 0:
        return 0
    obrnjeno = 0
    while n > 0:
        obrnjeno = obrnjeno * 10  + n % 10
        n = n // 10
    return obrnjeno

2. podnaloga

Najprej si oglejte naslednjo funkcijo. Ugotovite, kaj počne. Očitno jo je pisal nek programer začetnik, kar lahko zlahka ugotovimo po odsotnosti komentarjev in izbiri imen spremenljivk.

   def f(a, b):
       d = a % b # koliko še ostane
       k = 0
       r = '.'
       while k <=  10:
           d = d * 10
           nd = d // b
           r = r + str(nd)
           k = k + 1
           d = d % b
       return r

Namig: pokličite jo s parametri $7$, $3$; $2$, $4$; $154, $7$; $1$, $3$; $2$, $3$; $3$, $3$ in poskusi postaviti hipotezo, kaj se dogaja ...

Oboroženi z vedenjem o zgornji funkciji sestavite funkcijo kvocient(a, b, n), ki bo vrnila celi del in prvih n decimalk kvocienta a/b v obliki niza. Delaj samo s pozitivnimi celimi števili in na koncu NE zaokrožuj.

   >>>kvocient(10, 761, 40)
   0.0131406044678055190538764783180026281208
   >>>kvocient(100, 3, 14)
   33.33333333333333

Namig: kako delimo "peš"?

Uradna rešitev

def kvocient(a, b, n):
    """Izračunamo a/b na n decimalk (za dec. piko)"""
    celi_del = a // b
    rezultat = str(celi_del) + '.'
    delimo = a % b # koliko še ostane
    decimalke = 0
    while decimalke < n: # koliko decimalk potrebujemo
        delimo = delimo * 10
        nova_dec = delimo // b
        rezultat = rezultat + str(nova_dec) # dodamo decimalko
        decimalke = decimalke + 1 # je ena več
        delimo = delimo % b # za naslednji korak
    return rezultat

3. podnaloga

Programer Mihec je sestavil funkcijo vsebuje(a, k), ki naj bi povedala (True/False) če poljubno celo število a vsebuje števko k.

   def vsebuje(stevilo, k):
       ''' ali število stevilo vsebuje števko k '''
       while stevilo > 0:
           if stevilo % 10 == k:
               return True
           stevilo = stevilo // 10
       return False

Preizkusil jo je na storitvi Projekt Tomo, a je kar naprej dobival obvestila o napačnem rezultatu. Preizkusite jo še vi in jo ustrezno popravite!

Uradna rešitev

def vsebuje(stevilo, k):
    """ ali število stevilo vsebuje števko k """
    if (stevilo == 0) and (k == 0):
        return True
    stevilo = abs(stevilo) # zaradi neg. števil!
    while stevilo > 0:
        if stevilo % 10 == k:
            return True
        stevilo = stevilo // 10
    return False

4. podnaloga

Sestavite funkcijo prestej_vsebuje(a,b,k), ki prešteje, koliko števil med a in b (meji vključeni) vsebuje števko k. A pozor, lahko je tudi a >= b

Uradna rešitev

def prestej_vsebuje(a, b, k):
    """ prešteje koliko je med a in b števil, ki vsebujejo števko k """
    mini = min(a, b)
    maksi = max(a, b)
    stevilo = mini
    koliko = 0 # koliko jih zadošča pogoju
    while stevilo <= maksi:
        if vsebuje(stevilo, k):
            koliko += 1
        stevilo = stevilo + 1
    return koliko

5. podnaloga

Sestavite funkcijo prestej_prave(a,b,k), ki prešteje, koliko števil med a in b (0 <= a <= b), meji vključeni, vsebuje števko k ali pa so ona ali pa njihovi obrati deljivi s k.

Uradna rešitev

def vsebuje(stevilo, k):
    """ ali število stevilo vsebuje števko k """
    if stevilo == k == 0 :
        return True
    while stevilo > 0:
        if stevilo % 10 == k:
            return True
        stevilo = stevilo // 10
    return False

def obrni_stevilo(n):
    """ Funkcija obrne pozitivno celo število"""
    obrnjeno = 0
    while n > 0:
        obrnjeno = obrnjeno * 10  + n % 10
        n = n // 10
    return obrnjeno

def prestej_prave(a, b, k):
    """ prešteje koliko je med a in b števil, ki zadoščajo pogoju k """
    stevilo = a
    koliko = 0 # koliko jih zadošča pogoju
    while stevilo <= b:
        if vsebuje(stevilo, k) or stevilo % k == 0 or obrni_stevilo(stevilo) % k == 0:
            koliko += 1
        stevilo = stevilo + 1
    return koliko

Čokolade

1. podnaloga

Janezek ima nekaj čokolad. Prvi dan poje n čokolad, vsak naslednji dan pa jih poje dvakrat toliko kot prejšnji dan. Z babico sta dogovorjena, da bo dal dedku vse čokolade, ko bo čokolad manj kot je preteklo dni, od takrat ko je začel jesti čokolade.

Napišite funkcijo cokolade(st_cokolad, n), ki kot argumente sprejme število čokolad, ki jih ima in število n, ki pove koliko jih poje prvi dan. Funkcija naj vrne število čokolad, ki jih je Janezek dal dedku. Če poje vse čokolade dedek ne dobi nič.

Pomagaš si lahko z uporabo break.

>>> cokolade(0, 1)
0
>>> cokolade(2, 1)
1
>>> cokolade(3, 4)
0

Uradna rešitev

def cokolade(st_cokolad, n):
    """Funkcija vrne število čokolad, ki jih dobi dedek"""
    dan = 1
    while st_cokolad > 0:
        if st_cokolad < dan:         #če je število čokolad manj kot je število dni
            break
        st_cokolad -= n*(2**(dan - 1))
        if st_cokolad < 0:           #če je število čokolad negativno je Janezek pojedel vse
            st_cokolad = 0           #v tem primeru dedek ne dobi nič
        dan += 1
    return st_cokolad

2. podnaloga

Janezek pa je kmalu ugotovil, da dedek nebo dobil skoraj nič čokolad, zato se je odločil, da bo dal vsak dan eno čokolado na stran za svojega prijaznega dedka preden jih začne jesti.

Napišite funkcijo cokolade2(st_cokolad, n), ki kot argumente sprejme število čokolad, ki jih ima in število n, ki pove koliko jih poje prvi dan. Funkcija naj vrne število čokolad, ki jih je Janezek dal dedku. Če poje vse čokolade dedek ne dobi nič.

Pomagaš si lahko z uporabo break.

>>> cokolade2(0, 1)
0
>>> cokolade2(2, 1)
1
>>> cokolade2(3, 4)
1

Uradna rešitev

def cokolade2(st_cokolad, n):
    """Funkcija vrne število čokolad, ki jih dobi dedek"""
    dan = 1
    za_dedka = 0
    while st_cokolad > 0:
        za_dedka += 1
        st_cokolad -= 1
        if st_cokolad < dan:         #če je število čokolad manj kot je število dni
            break
        st_cokolad -= n*(2**(dan - 1))
        if st_cokolad < 0:           #če je število čokolad negativno je Janezek pojedel vse
            st_cokolad = 0           #v tem primeru dedek ne dobi nič
        dan += 1
    return st_cokolad + za_dedka

Mečemo kocko

1. podnaloga

Sestavite funkcijo dvakrat_zapored(), ki vrne število, ki pove, kolikokrat smo vrgli kocko, da smo dvakrat zapored vrgli 6. Če npr. mečemo

    2, 6, 3, 3, 6, 4, 5, 6, 6

smo torej kocko morali vreči 9x, da smo dvakrat zapored vrgli 6. Pomagajte si s knjižnico random in funkcijo randint().

Uradna rešitev

import random
def dvakrat_zapored():
    """"Koliko metov je potrebnih, da dvakrat zapored vržemo 6"""
    število_metov = 0
    prejšni_met = 42 # koliko smo vrgli v prejšnem metu (karkoli razen 6!)
    while True : # kar neskončna zanka, izstopili bomo z return
        met = random.randint(1,6)
        število_metov += 1
        if (met == 6) and (prejšni_met == 6):
            return število_metov
        prejšni_met = met

# še drugačna različica, brez break in while True
def dvakrat_zapored():
    """Koliko metov je potrebnih, da dvakrat zapored vržemo 6"""
    met = random.randint(1,6) # opravimo prvi met
    števec = 1
    prejšnji_met = 2 # karkoli, le 6 ne!!
    while not (prejšnji_met == 6 and met == 6):
        prejšnji_met = met
        met = random.randint(1,6) # novi met
        števec = števec + 1
    return števec

2. podnaloga

Sestavite funkcijo pricakovana_vrednost_dveh6(n), ki na podlagi n klicev prejšnje funkcije dvakrat_zapored() ugotovi, kolikokrat smo v povprečju v n poskusih morali vreči kocko, da smo dvakrat zapored vrgli 6.

Uradna rešitev

import random
def pricakovana_vrednost_dveh6(st_poskusov):
    '''Povprečje metov, potrebnih da dvakrat zaporedoma
       vržemo 6 v n poskusih '''
    skupno_št_metov = 0
    poskus = 1
    while poskus <= st_poskusov:
        število_metov = dvakrat_zapored() # opravimo eno poskus
        skupno_št_metov = skupno_št_metov + število_metov
        poskus = poskus + 1
    # povprečje
    return skupno_št_metov / st_poskusov

Igra ugibanj

1. podnaloga

Mamica in lukec se igrata igro ugibanj. Mamica ima na mizi 5 posode oštevilčene z 1, 2, 3, 4 in 5. Mamica Lukcu naključno skrije en bonbon v eno škatlo, lukec pa naključno ugotavlja, kam ga je skrila. Če ugotovi pravilno ga dobi in mamica skrije nov bonbon, če ne pa ne in Lukec nadaljuje z ugibanjem.

Sestavite funkcijo igraUgibanj(), ki simulira skrivanje in iskanje bonbona. Lukec ima na voljo 10 poskusov. Funkcija vrne število bonbonov, ki jih je lukec dobil na koncu igre. Pomagajte si s knjižnico random in funkcijo randint().

Uradna rešitev

import random
def igraUgibanj():
    '''funkcija simulira skrivanje in ugibanje ter vrne število bonbonov, ki
    jih je Lukec dobil'''
    stBonbonov = 0
    stPoskusov = 0
    while stPoskusov != 10:
        vKateriSkatli = random.randint(1, 5)
        while stPoskusov != 10:
            ugibanje = random.randint(1, 5)
            stPoskusov += 1
            if ugibanje == vKateriSkatli:
                stBonbonov += 1
                break
    return stBonbonov

2. podnaloga

Mamici je kmalu postalo dolgčas, zato je lukcu začela skrivati 3 bonbone naenkrat. Lukec ugotavlja dokler ne najde vseh treh, nato mu mamica skrije nove 3. Kar pa Lukec ne ve je to, da mu je mamica vedno skrila vse tri bonbonr v isto naključno škatlo.

Sestavite funkcijo igraUgibanj2(), ki simulira skrivanje in iskanje bonbona. Lukec ima na voljo 10 poskusov. Funkcija vrne število bonbonov, ki jih je lukec dobil na koncu igre.Pomagajte si s knjižnico random in funkcijo randint().

Uradna rešitev

import random
def igraUgibanj2():
    '''funkcija simulira skrivanje in ugibanje ter vrne število bonbonov, ki
    jih je Lukec dobil'''
    stBonbonov = 0
    stPoskusov = 0
    while stPoskusov != 10:
        vKateriSkatli = random.randint(1, 5)
        kolikoSeSkritih = 3
        while stPoskusov != 10:
            ugibanje = random.randint(1, 5)
            stPoskusov += 1
            if ugibanje == vKateriSkatli:
                stBonbonov += 1
                kolikoSeSkritih -= 1
                if kolikoSeSkritih == 0:
                    break
    return stBonbonov
Mesto objave ob koncu projekta 15.9.2018